package com.zhang.test;

import com.zhang.test.domain.vo.FileRetVO;
import com.zhang.bingmei_incomeexpenditure.entity.commom.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 图片上传控制器
 */
@RestController
@RequestMapping("/upload")
@CrossOrigin(origins = "*")
@Slf4j
public class UploadController {

    // 支持的图片类型后缀（与文件头验证对应）
    private final static String IMAGE_TYPE = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";

    /**
     * 图片上传接口
     * @param files 上传的图片文件数组
     * @return 上传结果（成功/失败信息 + 图片信息列表）
     */
    @PostMapping("/pic")
    public R<List<FileRetVO>> uploadPic(@RequestParam("files") MultipartFile[] files) {
        // 1. 校验文件数量（最多8张，因为 length >=9 则失败）
        if (files == null || files.length == 0) {
            return R.error("请选择至少1张图片");
        }
        if (files.length >= 9) {
            return R.error("最多支持8张图片上传");
        }

        // 2. 校验每个文件的合法性（文件头验证）
        for (MultipartFile file : files) {
            // 验证文件头（二进制签名）
            if (!validateFileHeader(file)) {
                String fileName = file.getOriginalFilename();
                log.warn("文件 {} 内容与类型不匹配，上传失败", fileName);
                return R.error("文件 " + fileName + " 内容与类型不匹配，请上传正确的图片文件");
            }
        }

        // 3. 模拟文件上传处理（实际项目中会调用文件服务上传到存储介质）
        List<FileRetVO> resultList = new ArrayList<>();
        for (MultipartFile file : files) {
            try {
                // 模拟上传：构造返回的文件信息（实际应从文件服务获取）
                FileRetVO fileRetVO = new FileRetVO();
                fileRetVO.setFileName(file.getOriginalFilename());
                fileRetVO.setFileSize(file.getSize());
                fileRetVO.setUrl("/uploaded/" + System.currentTimeMillis() + "_" + file.getOriginalFilename()); // 模拟URL
                resultList.add(fileRetVO);

                log.info("文件 {} 上传成功，大小：{} bytes", file.getOriginalFilename(), file.getSize());
            } catch (Exception e) {
                log.error("文件 {} 上传失败", file.getOriginalFilename(), e);
                return R.error("文件 " + file.getOriginalFilename() + " 上传失败，请重试");
            }
        }

        // 4. 返回成功结果
        return R.ok(resultList, "上传成功");
    }

    /**
     * 验证文件头（二进制签名），判断文件真实类型是否为支持的图片格式
     */
    private boolean validateFileHeader(MultipartFile file) {
        // 获取文件后缀名（用于辅助验证）
        String fileName = file.getOriginalFilename();
        if (fileName == null || !fileName.contains(".")) {
            return false; // 无后缀名，直接判定不合法
        }
        String extName = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();

        // 先校验后缀是否在支持的列表中
        if (!checkImageType(extName)) {
            log.warn("文件 {} 后缀 {} 不支持", fileName, extName);
            return false;
        }

        // 读取文件头字节进行二进制验证
        try (InputStream is = file.getInputStream()) {
            byte[] header = new byte[10]; // 读取前10字节（覆盖大部分图片格式的签名）
            int read = is.read(header);
            if (read < 1) {
                log.warn("文件 {} 内容为空", fileName);
                return false;
            }

            String hexHeader = bytesToHex(header); // 转为十六进制字符串

            // 根据后缀名匹配对应的文件头签名
            switch (extName) {
                case "bmp":
                case "dib":
                    return hexHeader.startsWith("424D"); // BMP/DIB 签名：BM
                case "gif":
                    return hexHeader.startsWith("47494638"); // GIF 签名：GIF8
                case "jpg":
                case "jpeg":
                    return hexHeader.startsWith("FFD8FF"); // JPG/JPEG 签名：FFD8FF
                case "png":
                    return hexHeader.startsWith("89504E47"); // PNG 签名：89504E47（PNG）
                case "tif":
                    return hexHeader.startsWith("49492A00") || hexHeader.startsWith("4D4D002A"); // TIFF 两种签名
                case "wmf":
                    return hexHeader.startsWith("D7CDC69A"); // WMF 签名
                case "eps":
                    return hexHeader.startsWith("252150532D41"); // EPS 签名：%!PS-Adobe
                case "psd":
                    return hexHeader.startsWith("38425053"); // PSD 签名：8BPS
                case "tga":
                    return hexHeader.startsWith("00000200") || hexHeader.startsWith("00001000"); // TGA 两种签名
                // 其他类型（pcp/dif等）暂不做严格签名验证，仅确保文件非空
                case "pcp":
                case "dif":
                case "cdr":
                case "iff":
                case "pcd":
                case "mpt":
                    return read > 0;
                default:
                    return false;
            }
        } catch (IOException e) {
            log.error("读取文件 {} 头失败", fileName, e);
            return false;
        }
    }

    /**
     * 校验文件后缀是否在支持的图片类型列表中
     */
    private boolean checkImageType(String extName) {
        // 将支持的类型转为小写并分割为数组，判断当前后缀是否包含其中
        String[] supportTypes = IMAGE_TYPE.toLowerCase().split(" ");
        for (String type : supportTypes) {
            if (type.equals(extName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 字节数组转十六进制字符串（用于文件头验证）
     */
    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b)); // 补0为两位十六进制
        }
        return sb.toString();
    }
}